﻿#include "levelscanningflowsession.h"
#include "common/datatypes.h"
#include "common/common.h"
#include <common/calcutils.h>
#include <common/calcutils.h>
#include "datamanager.h"
#include "testplanbuilder.h"

bool LevelScanningFlow::ensureSessionsForSubrange(const Exec::Subrange &subrange,
                                                  TestFlowSessionPtr reuseCandidate,
                                                  TestFlowSessionPtr &outSession,
                                                  TestFlowCallbacks callbacks,
                                                  QString &errorMessage)
{
    return true;
}

void LevelScanningFlow::safeMuteAllOutputs(const TestFlowSessionPtr &session)
{
    if (auto flowSession = std::dynamic_pointer_cast<LevelScanningFlowSession>(session)) {
        flowSession->safeMuteAllOutputs();
    }
}

bool LevelScanningFlow::measureOnePoint(const Exec::Subrange &subrange, int frequencyIndex, const TestFlowSessionPtr &session, TestFlowCallbacks callbacks, QString &errorMessage)
{
    return true;
}
bool LevelScanningFlow::measureLevelScanning(TestFlowCallbacks callbacks, const LevelScanningConfig &config, QString &errorMessage)
{
    if (config.freqStart_Hz <= 0.0) {
        qWarning() << "Invalid frequency step:" << config.freqStart_Hz;
        return false;
    }
    if (config.freqStart_Hz > config.freqStop_Hz) {
        qWarning() << "Start frequency is greater than stop frequency:" << config.freqStart_Hz << ">" << config.freqStop_Hz;
        return false;
    }

    // const int theoreticalPointCount = static_cast<int>(std::ceil((config.freqStop_Hz - config.freqStart_Hz) / config.freqStep_Hz + 1e-9)) + 1;
    const int theoreticalPointCount = static_cast<int>(std::ceil((config.freqStop_Hz - config.freqStart_Hz) / config.freqStep_Hz)) + 1;
    if (theoreticalPointCount <= 0) {
        qWarning() << "Calculated non-positive point count:" << theoreticalPointCount;
        return false;
    }
    TestPlanBuilder builder;
    TestSubBand tsb;
    tsb.startFreq = config.freqStart_Hz;
    tsb.stopFreq = config.freqStop_Hz;
    tsb.stepSize = config.freqStep_Hz;
    tsb.freqPlan = FrequencyPlanType::SweepLinear;
    tsb.stepMode = AxisScale::Linear;
    QVector<double> freqPoints = builder.expandFreqs(tsb, nullptr);

    /********** 衰减表 ************/
    const AttTableList attTable = DataManager::instance()->getAttTable(config.attTableID);
    if (freqPoints.isEmpty() || attTable.attList.isEmpty()) {
        qWarning() << "freqPoints.isEmpty() || attTable.attList.isEmpty()";
        return false;
    }
    Exec::CurvePtr attAligned = builder.makeAlignedCurve(builder.buildCurveFromAtt(attTable), tsb.stepMode, AxisScale::Linear, freqPoints);
    if ((freqPoints.size() != attAligned->xs_Hz.size()) || (attAligned->xs_Hz.size() != theoreticalPointCount)) {
        qWarning() << QString("freqPoints.size(%1) != attAligned->xs_Hz.size(%2) != theoreticalPointCount(%3)").arg(freqPoints.size()).arg(attAligned->xs_Hz.size()).arg(theoreticalPointCount);
        return false;
    }

    /********** 因子表 ************/
    const TransducerTableList tranTable = DataManager::instance()->getTransducerTable(config.factorTableID);
    if (freqPoints.isEmpty() || tranTable.factorsList.isEmpty()) {
        qWarning() << "freqPoints.isEmpty() || tranTable.factorsList.isEmpty()";
        return false;
    }
    Exec::CurvePtr FactorsAligned = builder.makeAlignedCurve(builder.buildCurveFromTransducer(tranTable), tsb.stepMode, AxisScale::Linear, freqPoints);
    if ((freqPoints.size() != FactorsAligned->xs_Hz.size()) || (FactorsAligned->xs_Hz.size() != theoreticalPointCount)) {
        qWarning() << QString("freqPoints.size(%1) != FactorsAligned->xs_Hz.size(%2) != theoreticalPointCount(%3)").arg(freqPoints.size()).arg(FactorsAligned->xs_Hz.size()).arg(theoreticalPointCount);
        return false;
    }

    if (FactorsAligned->sourceUnit != config.powerUnit) {
        qWarning() << "FactorsAligned->sourceUnit != config.powerUnit, " << FactorsAligned->targetUnit << config.powerUnit;
        return false;
    }

    const GeneralAttributes &ga = config.gAttributes;
    const DeviceType devType = ga.type;                  // DeviceType
    const DeviceInterfaceType ifType = ga.InterfaceType; // 枚举
    const QString &addr = ga.InterfaceAddr;              // "TCPIP0::1.2.3.4::5025::SOCKET" 等
    const QString &model = ga.Model;                     // 型号
    const QString &libPath = ga.LibraryPath;             //驱动
    auto session = std::make_shared<LevelScanningFlowSession>();

    // 解析 DLL 路径（你用自己的 resolver）
    const QString dllPath = Utils::instance()->resolveDriverPath(devType, libPath);
    const QString dllPathIO = Utils::instance()->resolveDriverPathIO(ifType);
    if (model != STR_NO_DEVICE && !dllPath.isEmpty() && !dllPathIO.isEmpty()) {
        // 通过 DeviceInstanceManager 创建实例，交给 DeviceHandle 管理
        session->receiverIO = makeDeviceHandle<IDeviceIO>(dllPathIO);
        session->receiver = makeDeviceHandle<IReceiver>(dllPath);
        if (!session->receiver || !session->receiverIO) {
            errorMessage = QString("Create receiver or IO instance failed: %1, %2").arg(dllPath).arg(dllPathIO);
            session->closeAll();
            return false;
        }
        session->receiver->setDeviceIO(session->receiverIO.get());

        if (!session->receiver->connect(addr)) {
            errorMessage = QString("receiver open failed: %1").arg(addr);
            session->closeAll();
            qCritical() << errorMessage;
            return false;
        }
    }
    if (callbacks.deviceMeasureStatus) {
        DeviceMeasureStatus dms;
        dms.role = DeviceRole::Receiver;
        dms.stat = DeviceStatus::Connected;
        callbacks.deviceMeasureStatus(dms);
    }

    if (!session->initReceiver()) {
        errorMessage = "init receiver fail";
        session->closeAll();
        qCritical() << errorMessage;

        DeviceMeasureStatus dms;
        dms.role = DeviceRole::Receiver;
        dms.stat = DeviceStatus::Abnormal;
        callbacks.deviceMeasureStatus(dms);
        return false;
    }
    (config.type == RS) ? session->receiver->setPowerUnit("DBM") : session->receiver->setPowerUnit("DBUV");
    bool st = false;
    st = session->receiver->setFrequencyMode("SCAN");
    st = session->receiver->setScanFrequencyRangeState(true, 1);
    st = session->receiver->setScanStartFrequency(config.freqStart_Hz, 1);
    st = session->receiver->setScanStopFrequency(config.freqStop_Hz, 1);
    st = session->receiver->setScanStepFrequency(config.freqStep_Hz, 1);
    st = session->receiver->setScanReferenceLevel(config.refLevel);
    st = session->receiver->setScanDwellTime(config.dwellTime, 1);
    if (config.inputAtten < 10)
        st = session->receiver->setAttenuationProtectionState(false);

    st = session->receiver->setScanATTenuation(config.inputAtten, 1);

#ifdef _ISALW
    st = session->receiver->setFormatData("REAL,32");
    st = session->receiver->writeString("DISP:TRAC:X:SPAC LIN;:TRAC:FEED:CONT ALW");

#else
    st = session->receiver->setFormatData("ASC");
#endif
    if (!st) {
        errorMessage = "receiver configuration fail";
        session->closeAll();
        qCritical() << errorMessage;
        return false;
    }

    if (callbacks.logLine)
        callbacks.logLine("start Scanning");
    else {
        errorMessage = "callbacks.logLine is nullptr!";
        return false;
    }
    ScanDataParser dataParser;
    for (int i = 0; i < config.repeatCont; i++) {
        if (callbacks.isStopRequested && callbacks.isStopRequested()) {
            errorMessage = "Stopped by user request";
            session->receiver->stopScan();
            session->closeAll();
            return true;
        }
        //这个接口中调用了INIT2:IMM\n
        session->receiver->startScan();
#ifndef _ISALW
        // QByteArray trace = session->receiver->writeRead(QByteArray("*WAI;:TRAC? TRACE1\n"));
        while (1) {
            if (trace.contains("\n"))
                break;
            trace += session->receiver->read();
            QThread::msleep(10);
        }
        trace = trace.trimmed();
        qDebug() << trace.size();
        QStringList list = QString::fromLocal8Bit(trace).split("\n");
        qDebug() << list.first().size();
        if (callbacks.levelScanData) {
            LevelScanningData data;
            if (buildFrequencyAndLevelArrays(config.type, FactorsAligned, config.safetyMargin, list.first(), data.freqPoints_Hz, data.levelPoints))
                callbacks.levelScanData(data);
        }
#else
        //使用点数的一半做为获取次数最大值
        int count = (config.freqStop_Hz - config.freqStart_Hz) / config.freqStep_Hz / 2;
        int totalPointsPlotted = 0;

        dataParser.clearBuffer();
        while (count > 0 && FactorsAligned->xs_Hz.size() > totalPointsPlotted) {
            if (callbacks.isStopRequested && callbacks.isStopRequested()) {
                errorMessage = "Stopped by user request";
                session->receiver->stopScan();
                session->closeAll();
                return true;
            }

            QByteArray trace = session->receiver->writeRead("TRAC? SCAN\n", 5);
            ScanResult result;
            if (dataParser.appendData(trace, result)) {
                // 检查是否有激活的Trace 1数据
                if (!result.traceActive[0] || result.traceData[0].isEmpty()) {
                    qDebug() << "No active Trace 1 data in this packet.";
                    session->receiver->stopScan();
                    session->closeAll();
                    return false;
                }

                const QVector<float> &levels = result.traceData[0];
                QVector<double> frequenciesHz(levels.size());
                QVector<double> levelsDouble(levels.size()); // QCustomPlot 需要 double
                // qDebug() << "result: " << result.traceData;
                // --- 核心逻辑：计算当前数据块的频率轴 ---
                for (int i = 0; i < levels.size(); ++i) {
                    // 计算当前点在整个扫描中的绝对索引
                    quint64 absolutePointIndex = totalPointsPlotted + i;
                    // 根据绝对索引和步进计算频率
                    double curFreq = config.freqStart_Hz + absolutePointIndex * config.freqStep_Hz;
                    int index = FactorsAligned->xs_Hz.indexOf(curFreq);
                    if (index < 0) {
                        frequenciesHz[i] = FactorsAligned->xs_Hz.last();
                        if (config.type == HardwareTemplateType::RS)
                            levelsDouble[i] = CalcUtils::dBm2Vm_general(static_cast<double>(levels[i]) + attAligned->ys.last(), FactorsAligned->ys.last(), 50); //天线因子
                        else
                            //CS测试：目标值为dBuA，dBuA= dBuV-dBohmn
                            //电流探头因子，如果不是dBuv,报错。
                            levelsDouble[i] = static_cast<double>(levels[i]) + attAligned->ys.last() - FactorsAligned->ys.last();
                        // levelsDouble[i] = static_cast<double>(levels[i]);
                        totalPointsPlotted += levels.size();
                        break;
                    }
                    frequenciesHz[i] = curFreq / 1e6;
                    if (config.type == HardwareTemplateType::RS)
                        levelsDouble[i] = CalcUtils::dBm2Vm_general(static_cast<double>(levels[i]) + attAligned->ys[index], FactorsAligned->ys[index], 50); //天线因子
                    else
                        //CS测试：目标值为dBuA，dBuA= dBuV-dBohmn
                        //电流探头因子，如果不是dBuv,报错。
                        levelsDouble[i] = static_cast<double>(levels[i]) + attAligned->ys[index] - FactorsAligned->ys[index];
                    // levelsDouble[i] = static_cast<double>(levels[i]);
                }
                totalPointsPlotted += levels.size();
                // qDebug() << "level: " << levelsDouble;
                // qDebug() << "freqw: " << frequenciesHz;
                if (callbacks.levelScanData) {
                    LevelScanningData calData;
                    calData.scanCount = i + 1;
                    const int actualPointCount = levels.size();    // 使用实际解析出的点数
                    calData.levelPoints.reserve(actualPointCount); // levels 将直接使用 parsedLevels 的数据
                    calData.freqPoints_Hz.reserve(actualPointCount);

                    calData.levelPoints = std::move(levelsDouble);
                    calData.freqPoints_Hz = std::move(frequenciesHz);
                    callbacks.levelScanData(calData);
                }
            }
            count--;
        }

#endif
        QThread::msleep(3000);
    }

    session->closeAll();
    return true;
}

bool LevelScanningFlow::buildFrequencyAndLevelArrays(const HardwareTemplateType type, Exec::CurvePtr &factors, const double safetyMargin, const QString &traceDataString, QVector<double> &frequenciesHz, QVector<double> &levels)
{
    // 1. 清空输出数组
    frequenciesHz.clear();
    levels.clear();

    // 4. 解析 trace 数据
    QStringList levelStringList = traceDataString.split(',');
    QVector<double> parsedLevels, parsedFreqs;
    parsedLevels.reserve(levelStringList.size());
    parsedFreqs.reserve(levelStringList.size());
    if ((levelStringList.size() != factors->ys.size()) || (factors->ys.size() != factors->xs_Hz.size())) {
        qWarning() << "Mismatch between theoretical point count (" << factors->ys.size()
                   << ") and device trace data count (" << parsedLevels.size() << ")";

        return false;
    }
    for (int i = 0; i < levelStringList.size(); ++i) {
        bool ok = false;
        //dBm dBuV
        double levelValue = levelStringList.at(i).toDouble(&ok);
        if (!ok) {
            qWarning() << "Failed to parse level value from string:" << levelStringList.at(i);
            return false;
        }
        levelValue += safetyMargin;
        parsedFreqs.append(factors->xs_Hz[i] / 1e6);
        double immunityLevel;
        if (type == HardwareTemplateType::RS)
            immunityLevel = CalcUtils::dBm2Vm_general(levelValue, factors->ys[i], 50); //天线因子
        else
            //CS测试：目标值为dBuA，dBuA= dBuV-dBohmn
            //电流探头因子，如果不是dBuv,报错。
            immunityLevel = levelValue - factors->ys[i];
        // qDebug() << "__immunityLevel_" << immunityLevel;
        // qDebug() << "__levelValue_" << levelValue;
        // qDebug() << "__factors->ys[i]_" << factors->ys[i] << endl;
        parsedLevels.append(immunityLevel);
    }

    const int actualPointCount = parsedLevels.size(); // 使用实际解析出的点数

    levels.reserve(actualPointCount); // levels 将直接使用 parsedLevels 的数据
    frequenciesHz.reserve(actualPointCount);
    levels = std::move(parsedLevels);
    frequenciesHz = std::move(parsedFreqs);
    return true;
}

void LevelScanningFlow::setPlanOptions(const FlowPlanOptions &opts)
{
    options_ = opts;
}

void LevelScanningFlowSession::safeMuteAllOutputs()
{
    rfMuted = true;
}

bool LevelScanningFlowSession::ensureOutputsEnabled()
{
    rfMuted = false;
    return true;
}

bool LevelScanningFlowSession::initReceiver()
{
    bool isRec = (receiver) ? true : false;
    if (isRec) {
        //        { //9038与rs设备reset功能不同，9038reset不改变工作模式，而rs esu则会改变
        //            if (!receiver->setInstrumentSelect("REC"))
        //                return false;

        //            QThread::msleep(3000);
        //        }
        if (!receiver->reset())
            return false;
        if (!receiver->setInstrumentSelect("REC"))
            return false;

        if (!receiver->setInitiateContinuousState(0))
            return false;
    }
    return isRec & true;
}

bool LevelScanningFlowSession::init()
{
    return true;
}

void LevelScanningFlowSession::closeAll()
{
    closeAndResetAll(receiver);
    resetAll(receiverIO);
}

ScanDataParser::ScanDataParser(QObject *parent)
    : QObject(parent)
{
}

bool ScanDataParser::appendData(const QByteArray &newData, ScanResult &result)
{
    m_buffer.append(newData);
    return tryParseNextPacket(result);
}

bool ScanDataParser::tryParseNextPacket(ScanResult &result)
{
    // 1. 寻找包起始符 '#'
    int startMarkerPos = m_buffer.indexOf('#');

    if (startMarkerPos == -1) {
        // 缓冲区中没有起始符，无法开始解析。
        // 如果缓冲区过大，可能需要清空以防内存耗尽，这里暂时不清空
        // 因为'#'可能在下一个数据块中才到达
        return false;
    }

    // 丢弃起始符前的所有无效数据
    if (startMarkerPos > 0) {
        qWarning() << "Discarding" << startMarkerPos << "bytes of invalid data from buffer.";
        m_buffer.remove(0, startMarkerPos);
    }

    // 解析头部，确定数据包总长度
    // 至少需要3个字节来开始解析头部 (# + 1位长度 + 1位数据长度)
    if (m_buffer.length() < 3) {
        return false; // 头部数据不完整，等待更多数据
    }

    // 获取描述长度的位数 (例如 '#45024' 中的 '4')
    int lengthOfLength = m_buffer.at(1) - '0'; // ASCII to int
    if (lengthOfLength <= 0 || lengthOfLength > 9) {
        qWarning() << "Invalid header format: length-of-length is invalid. Discarding '#'.";
        m_buffer.remove(0, 1); // 移除错误的 '#'，以便下次寻找
        return false;          // 返回false，但appendData会再次调用本函数继续寻找
    }

    int headerSize = 2 + lengthOfLength;
    if (m_buffer.length() < headerSize) {
        return false; // 头部数据不完整，等待更多数据
    }

    // 获取负载数据长度 (例如 '#45024' 中的 '5024')
    bool ok;
    qint64 payloadLength = m_buffer.mid(2, lengthOfLength).toLongLong(&ok);
    if (!ok) {
        qWarning() << "Invalid header format: payload length is not a number. Discarding '#'.";
        m_buffer.remove(0, 1);
        return false;
    }

    qint64 totalPacketSize = headerSize + payloadLength;

    // 检查缓冲区中是否有足够的数据构成一个完整的包
    if (m_buffer.length() < totalPacketSize) {
        return false; // 数据不完整，等待更多数据
    }

    // 截取并解析完整的数据包
    QByteArray completePacket = m_buffer.left(totalPacketSize);
    bool parseSuccess = parseCompletePacket(completePacket, result);

    //从缓冲区移除已处理的数据包
    m_buffer.remove(0, totalPacketSize);

    return parseSuccess;
}

void ScanDataParser::clearBuffer()
{
    m_buffer.clear();
}

bool ScanDataParser::parseCompletePacket(const QByteArray &packet, ScanResult &result)
{
    int lengthOfLength = packet.at(1) - '0';
    int headerSize = 2 + lengthOfLength;

    QByteArray payload = packet.mid(headerSize);
    QDataStream stream(payload);
    stream.setByteOrder(QDataStream::LittleEndian);
    stream.setFloatingPointPrecision(QDataStream::SinglePrecision);

    // 开始解析负载
    stream >> result.rawTraceStatus;
    result.parseTraceStatus();

    stream >> result.numberOfPoints;

    quint32 t1_s, t2_s, t3_s, t4_s;
    stream >> t1_s >> t2_s >> t3_s >> t4_s;
    result.traceActive[0] = (t1_s & 1);
    result.traceActive[1] = (t2_s & 1);
    result.traceActive[2] = (t3_s & 1);
    result.traceActive[3] = (t4_s & 1);
    result.traceActive[4] = (t1_s >> 8) & 1;
    result.traceActive[5] = (t2_s >> 8) & 1;

    for (int i = 0; i < 6; ++i) {
        if (result.traceActive[i]) {
            result.traceData[i].resize(result.numberOfPoints);
            for (quint32 j = 0; j < result.numberOfPoints; ++j) {
                if (stream.atEnd())
                    return false; // 检查数据完整性
                stream >> result.traceData[i][j];
            }
        }
    }

    result.statusBytes.resize(result.numberOfPoints);
    for (quint32 j = 0; j < result.numberOfPoints; ++j) {
        if (stream.atEnd())
            return false;
        stream >> result.statusBytes[j];
    }

    return true;
}
